home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DDJ0992.ARJ / DUNHAM.LS7 < prev    next >
Text File  |  1992-04-20  |  50KB  |  1,409 lines

  1. /* Listing #7: sparc.c     signal handling & stack traceback */
  2.  
  3. #include <stdio.h>
  4. #include <signal.h>        /* for signal definitions */
  5. #include <a.out.h>        /* for NSYMOFF etc */
  6. #include <stab.h>        /* for N_SLINE etc */
  7. #include <string.h>        /* for strtok */
  8. #include <floatingpoint.h>    /* for fpe handling */
  9.  
  10. /*----------------- local defines --------------------*/
  11. #undef PROTOTYPES         /* ignore prototype info */
  12. #undef DEBUGPRINT        /* we don't want debug info */
  13. #define STACKDUMP 0        /* set to 1 to get 32bit stack dumps */
  14. #define FRAMEDUMP 0        /* set to 1 to dump each stack frame */
  15. #define PARAMDUMP 0        /* set to 1 to get parameter dumps */
  16. #define SYMBOLDUMP 0        /* set to 1 to get local symbol dumps */
  17.  
  18. #define JUMPPC 15        /* how to find next program counter */
  19. #define JUMPSP 14        /* how to find next stack pointer */
  20. #define MAXLEVEL 40        /* maximum number of nested subroutine calls */
  21. #define MAXPARAM 40        /* maximum number of subroutine parameters */
  22. #define DUMPSIZE 256        /* size of stack dump in longwords */
  23. #define NSIGNAL 31              /* #signals to describe in text array */
  24. #define STREQ(a,b)  (strcmp((a),(b))==0)
  25. #define STRNEQ(a,b) (strcmp((a),(b))!=0)
  26. #define CNULL '\0'
  27.  
  28. #ifdef PROTOTYPES
  29. # define P_(s) s
  30. #else
  31. # define P_(s) ()
  32. #endif
  33. #ifdef DEBUGPRINT
  34. # define DBPRINT(s) printf s
  35. #else
  36. # define DBPRINT(s) 
  37. #endif
  38.  
  39. /* defines for data dictionary: basic types */
  40. #define D_INT 1
  41. #define D_CHAR 2
  42. #define D_LONG 3
  43. #define D_SHORT 4
  44. #define D_UCHAR 5
  45. #define D_USHORT 6
  46. #define D_ULONG 7
  47. #define D_UINT 8
  48. #define D_FLOAT 9
  49. #define D_DOUBLE 10
  50. #define D_VOID 11
  51. #define D_NONE 12
  52.  
  53. /*----------------- external functions --------------------*/
  54. char *malloc();
  55. char *getenv();
  56.  
  57. /*----------------- internal functions --------------------*/
  58. static void trb_exefind P_((int argc, char *argv));
  59. static void trb_exeinfo();
  60. static void trb_dictionary P_((int ilevel, FILE fp, FILE fp2));
  61. static void trb_symboldump();
  62. static void trb_stackdump P_((unsigned long start, int nn, FILE **fp));
  63. static void trb_framedump P_((unsigned long sp, unsigned long pc,
  64.                              unsigned long fremeend, FILE **fp));
  65. static void trb_getline P_((int nlevel));
  66. static void trb_params P_((int ilevel, FILE fp, FILE fp2));
  67. static void trb_symbols P_((int ilevel, FILE fp, FILE fp2));
  68. static void trb_traceback P_((int nlevel));
  69. void trb_userinfo P_((FILE fp));
  70. void trb_handle P_((int sig,int code,struct sigcontext *scp, char *addr));
  71. static void trb_sigtextinit();
  72. static char *trb_codetext P_((int sig, int code));
  73. static void trb_signal();
  74. void trb_signalinit P_((int argc, char *argv[]));
  75. static char *strstr();
  76. static void str_getdelimited P_((char *inttext, char *bounds,
  77.                  char *outtext));
  78. static void str_whiteout P_((char *string, char *chars));
  79.  
  80. /*----------------- structure definitions -----------------*/
  81. struct levelstr       /* info for each function in traceback */
  82.   {unsigned long stackpointer;    /* start of stack frame */
  83.    unsigned long programcounter;  /* return address */
  84.    unsigned long frameend;        /* end of stack frame (+4) */
  85.    long fileaddr,funcaddr;        /* addresses into string table */
  86.    char funcname[256];            /* name of function */
  87.    char filename[256];            /* name of source file */
  88.    int found;                     /* 0 if function not found */
  89.    int filesymbol;                /* symbol # for start of source file */
  90.    int funcsymbol;                /* symbol # for start of function */
  91.    int line;                      /* line number in source file */
  92.   };
  93.  
  94. struct exestr      /* information about the executable file */
  95.   {int nsym;             /* number of symbols in symbol table */
  96.    unsigned long magic;  /* the magic number of the file */
  97.    long stroffset;       /* offset to the string table */
  98.    long symoffset;       /* offset to the symbol table */
  99.    char name[256];       /* path to the file */
  100.   };
  101.  
  102. struct dictstr     /* a dictionary of defined variable types */
  103.   {char match[8];        /* the defined type (0,nnn) */
  104.    char basetype[8];        /* what it is defined from (0,nnn) */
  105.    int code;            /* our base identifier ie D_INT */
  106.    char fullstring[80];        /* as it was read from COFF */
  107.    int ptr;            /* 1 if it is a pointer */
  108.    int lower,upper;        /* array bounds */
  109.   };
  110.  
  111.   
  112. /*----------------- global variables ----------------------*/
  113. char   sigtext[NSIGNAL+1][64];    /* describe signal values */
  114. struct levelstr level[MAXLEVEL];  /* one per stack frame */
  115. struct exestr exe;
  116. struct dictstr dictionary[200];   /* allow 200 per source file */
  117. int ndict;                        /* number of types per source file */
  118. FILE   *fpcrash,*fpstackdump,*fpframedump;
  119.           /* pointers to files CRASH, STACKDUMP, FRAMEDUMP */
  120. char description[13][16] = {"???","int","char","long","short","unsigned char",
  121.                  "unsigned short","unsigned long","unsigned int","float",
  122.                 "double","void","???" };
  123.   
  124. /****************************************************************/
  125. /*    trb_exefind                        */
  126. /*    find the path of the file we are executing        */
  127. /****************************************************************/
  128. static void trb_exefind(argc,argv)
  129. int argc;
  130. char *argv[];
  131. {
  132.   FILE *fp;
  133.   int ll;
  134.   char name[256],*path;
  135.   char *ptr,trial[256];
  136. /*---------------------------------*/
  137. /* get name of program */
  138.   strcpy(name,argv[0]);
  139.   
  140. /* 1: if name contains a slash, assume it is the direct path */
  141.   ptr= strchr(name,'/');
  142.   if(ptr!=NULL)
  143.     {strcpy(trial,name);
  144.      fp= fopen(trial,"r");
  145.      if(fp!=NULL)
  146.        {fclose(fp);strcpy(exe.name,trial);return;}
  147.     }
  148.       
  149. /* 2: look in the user's path */
  150.   ptr= getenv("PATH");
  151.   ll= strlen(ptr);
  152.   path= malloc(ll+1);
  153.   strcpy(path,ptr);
  154. /* separate path string into its components */
  155.   ptr= strtok(path,":");
  156.   while(ptr!=NULL)
  157.     {strcpy(trial,ptr);
  158.      strcat(trial,"/");
  159.      strcat(trial,name);
  160.      DBPRINT(("trial exe is %s \n",trial));
  161.      fp= fopen(trial,"r");
  162.      if(fp!=NULL) {fclose(fp);strcpy(exe.name,trial);free(path);return;}
  163.      ptr= strtok(NULL,":");
  164.     }
  165.  
  166. /* 3: try the local directory in case it is not in the path */
  167.   strcpy(trial,"./");
  168.   strcat(trial,name);
  169.   DBPRINT(("trial exe is %s \n",trial));
  170.   fp= fopen(trial,"r");
  171.   if(fp!=NULL){fclose(fp);strcpy(exe.name,trial);return;}
  172.  
  173. } /* end of trb_exefind */
  174.  
  175. /****************************************************************/
  176. /*    trb_exeinfo                        */
  177. /*    get needed info from executable file header        */
  178. /****************************************************************/
  179. static void trb_exeinfo()
  180. {
  181.   int status;
  182.   unsigned long magic;
  183.   FILE *fp;
  184.   struct exec header;    /* exe file header (from a.out.h) */
  185.   struct nlist symbol;    /* symbol table entry */
  186. /*--------------------*/
  187. /* open exe file */
  188.   fp= fopen(exe.name,"r");
  189.   if(fp==NULL)
  190.     {printf("can't open %s\n",exe.name);
  191.      exit(1);}
  192.   
  193. /* read the file header */
  194.   status= fread(&header,sizeof(header),1,fp);
  195.   if(status==0) {printf("could not read header\n"); exit(2);}
  196.  
  197. /* is the magic number okay ? */
  198.   magic= header.a_magic;
  199.   status= N_BADMAG(header);
  200.   if(status!=0)
  201.     {printf("bad magic number = %ld 0x%lx 0%lo \n",magic,magic,magic);
  202.      exit(3);
  203.     }
  204.   exe.magic= magic;
  205.  
  206. /* how big is the symbol table */
  207.   exe.nsym= header.a_syms/sizeof(symbol);
  208.   if(exe.nsym==0) exit(4);
  209.  
  210. /* get file offsets for symbol table & string table */
  211.   exe.symoffset= N_SYMOFF(header);
  212.   exe.stroffset= N_STROFF(header);
  213.  
  214.   fclose(fp);
  215. } /* end of trb_exeinfo */
  216.   
  217. /****************************************************************/
  218. /*    trb_dictionary                        */
  219. /*    make a "data dictionary" for a source file        */
  220. /****************************************************************/
  221. static void trb_dictionary(ilevel,fp,fp2)
  222. int ilevel;
  223. FILE *fp, *fp2;
  224. {
  225.   int i,j,status,type,off;
  226.   int low,high,code,pointer;
  227.   int isym;
  228.   struct nlist symbol;    /* symbol table entry */
  229.   long nseek;
  230.   char *ptr, *ptr2;
  231.   char ttext[1024],tempstring[64];
  232.   char symbolname[32],junk1[8],junk2[8],match[8];
  233. /*--------------------*/
  234.   dictionary[0].code=D_INT;
  235.   dictionary[1].code=D_CHAR;
  236.   dictionary[2].code=D_LONG;
  237.   dictionary[3].code=D_SHORT;
  238.   dictionary[4].code=D_UCHAR;
  239.   dictionary[5].code=D_USHORT;
  240.   dictionary[6].code=D_ULONG;
  241.   dictionary[7].code=D_UINT;
  242.   dictionary[8].code=D_FLOAT;
  243.   dictionary[9].code=D_DOUBLE;
  244.   dictionary[10].code=D_VOID;
  245.   dictionary[11].code=D_NONE;
  246.   strcpy(dictionary[0].match,"0,1");
  247.   strcpy(dictionary[1].match,"0,2");
  248.   strcpy(dictionary[2].match,"0,3");
  249.   strcpy(dictionary[3].match,"0,4");
  250.   strcpy(dictionary[4].match,"0,5");
  251.   strcpy(dictionary[5].match,"0,6");
  252.   strcpy(dictionary[6].match,"0,7");
  253.   strcpy(dictionary[7].match,"0,8");
  254.   strcpy(dictionary[8].match,"0,9");
  255.   strcpy(dictionary[9].match,"0,10");
  256.   strcpy(dictionary[10].match,"0,11");
  257.   strcpy(dictionary[11].match,"0,12");
  258.   for(i=0;i<12;i++)
  259.     {dictionary[i].ptr=0;
  260.      dictionary[i].lower=0;
  261.      dictionary[i].upper=0;
  262.      dictionary[i].basetype[0]=CNULL;
  263.     }
  264.  
  265. /* open exe file */
  266.   fp= fopen(exe.name,"r");
  267.   fp2= fopen(exe.name,"r");
  268.   if(fp==NULL)
  269.     {printf("can't open %s\n",exe.name);
  270.      exit(1);}
  271.   ndict=12;
  272.   isym= level[ilevel].filesymbol+1;  /* seek to source files' symbols */
  273.   nseek= exe.symoffset + isym*sizeof(symbol);
  274.   fseek(fp,nseek,0);
  275.   for(i=isym;i<exe.nsym;i++)
  276.     {status= fread(&symbol,sizeof(symbol),1,fp);
  277.      if(status==0) printf("could not read symbol\n");
  278.      type= symbol.n_type;
  279.      if(type==N_SO) return; /* we are at the next source file */
  280.      if(type!=N_LSYM && type!=N_PSYM) continue;  /* local syms & params */
  281.      nseek= exe.stroffset+symbol.n_un.n_strx;
  282.      fseek(fp2,nseek,0);
  283.      ptr= fgets(ttext,sizeof(ttext),fp2);   /* text describing symbol */
  284.      /* ignore structures for now */
  285.      str_getdelimited(ttext,"()",match);
  286.      if(match[0]!='0') continue;
  287.      /* is it a basic type */
  288.      ptr= strstr(ttext,":t(");
  289.      if(ptr!=NULL)continue;
  290.      /* extract the symbol name */
  291.      strcpy(tempstring,ttext);
  292.      str_whiteout(tempstring,":=;");
  293.      sscanf(tempstring,"%s",symbolname);
  294.      /* if an old type, go to next symbol */
  295.      ptr=strchr(ttext,'=');
  296.      if(ptr==NULL)continue;
  297.      /* it is a new type, clear some flags */
  298.      dictionary[ndict].ptr= 0;
  299.      dictionary[ndict].code= 0;
  300.      dictionary[ndict].lower= 0;
  301.      dictionary[ndict].upper= 0;
  302.      strcpy(dictionary[ndict].match,match);
  303.      /* is this new type a pointer */       
  304.      ptr2=strstr(ptr,"=*(");
  305.      if(ptr2!=NULL)
  306.        {str_getdelimited(ptr2,"()",match);
  307.         strcpy(dictionary[ndict].basetype,match);
  308.         dictionary[ndict].ptr= 1;
  309.         for(j=0;j<ndict;j++)
  310.           {if(STREQ(match,dictionary[j].match))
  311.          {code= dictionary[j].code;
  312.               pointer= dictionary[j].ptr+1;
  313.               dictionary[ndict].code= code;
  314.               dictionary[ndict].ptr= pointer;
  315.               break;
  316.              }
  317.           }
  318.         ndict++;
  319.         continue;
  320.        }
  321.      /* is this new type an array */
  322.      ptr2=strstr(ptr,"=ar(");
  323.      if(ptr2!=NULL)
  324.        {strcpy(tempstring,ptr);
  325.     str_whiteout(tempstring,";()");
  326.     sscanf(tempstring,"%s %s %d %d %s",junk1,junk2,&low,&high,match);
  327.       strcpy(dictionary[ndict].basetype,match);
  328.         dictionary[ndict].lower= low;
  329.         dictionary[ndict].upper= high;
  330.     for(j=0;j<ndict;j++)
  331.           {if(STREQ(match,dictionary[j].match))
  332.          {code=dictionary[j].code;
  333.               dictionary[ndict].code=code;
  334.               break;
  335.              }
  336.           }
  337.         ndict++;
  338.         continue;
  339.        }
  340.  
  341.    }  /* end of loop over all symbols */
  342.  
  343. } /* end of trb_dictionary */
  344.   
  345. /****************************************************************/
  346. /*    trb_translate                        */
  347. /*    what kind of variable is a symbol            */
  348. /****************************************************************/
  349. static void trb_translate(ttext,code,pointer,array)
  350. char *ttext;
  351. int *code, *pointer, *array;
  352. {
  353.   int i,j,status,type,off;
  354.   int low,high,size;
  355.   int isym;
  356.   struct nlist symbol;    /* symbol table entry */
  357.   long nseek;
  358.   char *ptr, *ptr2;
  359.   char tempstring[64];
  360.   char symbolname[32],junk1[8],junk2[8],match[8];
  361. /*--------------------*/
  362. /* zero the output flags */
  363.   *code= 0;
  364.   *pointer= 0;
  365.   *array= 0;
  366. /* ignore structures for now */
  367.   str_getdelimited(ttext,"()",match);
  368.   if(match[0]!='0') return;
  369. /* look in the data dictionary */
  370.     {for(j=0;j<ndict;j++)
  371.        {if(STREQ(match,dictionary[j].match))
  372.           {*code= dictionary[j].code;
  373.            *pointer= dictionary[j].ptr;
  374.            size= dictionary[j].upper-dictionary[j].lower+1;
  375.        if(size>1) *array=size;
  376.            return;
  377.           }
  378.        }
  379.      return;
  380.     }           
  381. } /* end of trb_translate */
  382.  
  383. /****************************************************************/
  384. /*    trb_verbalize                        */
  385. /*    print what kind of variable a symbol is            */
  386. /****************************************************************/
  387. static void trb_verbalize(name,code,pointer,array)
  388. char *name;
  389. int code,pointer,array;
  390. {
  391.   char ttext[80],size[16];
  392. /*------------------------------------------------------*/
  393.   strcpy(ttext,name);           
  394.   if(pointer>0)
  395.     strcat(ttext," is a pointer to type ");
  396.   else if(array>1)
  397.     strcat(ttext," is an array of type ");
  398.   else
  399.     strcat(ttext," is a variable of type ");
  400.   if(pointer==2) strcat(ttext,"*");
  401.   if(pointer==3) strcat(ttext,"*");
  402.   strcat(ttext,description[code]);
  403.  
  404.   if(array>1) {sprintf(size," [%d] ",array); strcat(ttext,size); } 
  405.   printf("%s\n",ttext);  
  406. } /* end of trb_verbalize */
  407.  
  408. /****************************************************************/
  409. /*    trb_symboldump                        */
  410. /*    dump text of local symbols                 */
  411. /****************************************************************/
  412. static void trb_symboldump()
  413. {
  414.   int i,j,status,type,off;
  415.   FILE *fp, *fp2, *fpout;
  416.   struct nlist symbol;    /* symbol table entry */
  417.   long nseek;
  418.   char *ptr, *ptr2;
  419.   char ttext[1024];
  420.   long fileaddr;
  421.   char filename[256];
  422. /*--------------------*/
  423. /* open exe file */
  424.   fp= fopen(exe.name,"r");
  425.   fp2= fopen(exe.name,"r");
  426.   if(fp==NULL)
  427.     {printf("can't open %s\n",exe.name);
  428.      exit(1);}
  429. /* open file SYMBOLDUMP */
  430.   fpout= fopen("SYMBOLDUMP","w");
  431.   if(fpout==NULL)
  432.     {printf("can't open file SYMBOLDUMP for output\n");
  433.      exit(1);}
  434.   trb_userinfo(fpout);
  435.   fseek(fp,exe.symoffset,0);
  436.   for(i=0;i<exe.nsym;i++)
  437.     {status= fread(&symbol,sizeof(symbol),1,fp);
  438.      if(status==0) printf("could not read symbol\n");
  439.      type= symbol.n_type;
  440.      if(type==N_SO)    /* source file name: name,,0,0,address */
  441.        {fileaddr= symbol.n_un.n_strx;
  442.         fseek(fp2,exe.stroffset,0);
  443.         fseek(fp2,fileaddr,1);
  444.         ptr= fgets(filename,sizeof(filename),fp2);
  445.         fprintf(fpout,"filename %s \n",filename);
  446.        }
  447.      if(type!=N_LSYM) continue;
  448.      off= symbol.n_value;
  449.      nseek= exe.stroffset+symbol.n_un.n_strx;
  450.      fseek(fp2,nseek,0);
  451.      ptr= fgets(ttext,sizeof(ttext),fp2);
  452.      fprintf(fpout,"frame offset=%d symbol text: >%s< \n",off,ttext);
  453.    }  /* end of loop over all symbols */
  454.  
  455.   fclose(fp);
  456.   fclose(fp2);
  457.   fclose(fpout);
  458. } /* end of trb_symboldump */
  459.   
  460. /****************************************************************/
  461. /*    trb_stackdump                        */
  462. /*    dump the stack                        */
  463. /****************************************************************/
  464. static void trb_stackdump(start,nn,fp0)
  465. unsigned long start;
  466. int nn;
  467. FILE **fp0;
  468. {
  469.   int i,j;
  470.   FILE *fp;
  471. /*------------------------------------------------------*/
  472.   fp= *fp0;
  473.   if(fp==0)
  474.     {fp= fopen("STACKDUMP","a"); /* open for append */
  475.      if(fp==NULL) fp= stdout; /* if failure, use standard out */
  476.      *fp0= fp;                /* save it in case we have two crashes */
  477.     }
  478.   trb_userinfo(fp);
  479.   for (i=0; i<nn;i++)
  480.     {fprintf(fp,"%08x ", (long)start);
  481.      fprintf(fp,"%08x ", *(unsigned long *)(start));
  482.      for(j=0;j<4;j++,start++)
  483.        fprintf(fp,"%c",   isprint(*(unsigned char *)(start))
  484.              ? *(unsigned char *)(start) : ' ');
  485.      fprintf(fp,"\n");
  486.     }
  487.   fclose(fp);
  488. } /* end of trb_stackdump */
  489.  
  490. /****************************************************************/
  491. /*    trb_framedump                        */
  492. /*    dump a stack frame                    */
  493. /****************************************************************/
  494. static void trb_framedump(stackpointer,programcounter,frameend,fp0)
  495. unsigned long stackpointer,programcounter,frameend;
  496. FILE **fp0;
  497. {  
  498.   int j;
  499.   unsigned long stackaddress,stackvalue;
  500.   FILE *fp;
  501. /*------------------------------------------------------*/
  502.   fp= *fp0;
  503.   if(fp==0)
  504.     {fp= fopen("FRAMEDUMP","a"); 
  505.      if(fp==NULL) fp= stdout;
  506.      trb_userinfo(fp);
  507.      *fp0= fp;
  508.     }
  509.   fprintf(fp,"-----------------------------------\n");
  510.   fprintf(fp,"sp=%08x pc=%08x\n",stackpointer,programcounter);
  511.   j= 0;
  512.   stackaddress= stackpointer;
  513.   while(stackaddress<frameend)
  514.     {stackvalue= *( (long *)stackaddress);
  515.      fprintf(fp," %8x",stackvalue);
  516.      j++;
  517.      if(j==8) {fprintf(fp,"\n");j= 0;}
  518.      stackaddress= stackaddress+4;
  519.     }
  520.   if(j!=0)fprintf(fp,"\n");
  521.   fprintf(fp,"-----------------------------------\n");
  522. } /* end of trb_framedump */
  523.  
  524. /****************************************************************/
  525. /*    trb_getline                        */
  526. /*    find file lines matching addresses            */
  527. /****************************************************************/
  528. static void trb_getline(nlevel)
  529. int nlevel;
  530. {
  531.   FILE *fp,*fp2;
  532.   struct nlist symbol;    /* symbol table entry */
  533.   unsigned long address,match,lastaddress;
  534.   int type,line,funcsymbol,filesymbol;
  535.   int i,j,ll,status;
  536.   long fileaddr,funcaddr,magic;
  537.   int iff;
  538.   char *ptr,ttext[256];
  539.   char funcname[256],filename[256];
  540. /*----------------------*/
  541. /* initialize */
  542.   address= 0; funcsymbol= 0; filesymbol=0;
  543.   lastaddress= 0xFFFF;
  544.   for(i=0;i<MAXLEVEL;i++)level[i].found= 0;
  545.   DBPRINT(("in trb_getline: nlevel=%d pc[0]=%x\n",nlevel,level[0].pc));
  546.  
  547. /* use first file pointer to read symbol table */
  548.   fp= fopen(exe.name,"r");
  549.   if(fp==NULL) {printf("can't open %s\n",exe.name);exit(1);}
  550. /* use second file pointer to read the string table */
  551.   fp2= fopen(exe.name,"r");
  552.   
  553. /* read all symbols, look at source lines, file & function names */
  554.   fseek(fp,exe.symoffset,0);
  555.   for(i=0;i<exe.nsym;i++)
  556.     {status= fread(&symbol,sizeof(symbol),1,fp);
  557.      if(status==0) printf("could not read symbol\n");
  558.      type= symbol.n_type;
  559. /* what type of symbol is it */
  560.      if(type==N_SLINE)        /* src line: 0,,0,linenumber,address */
  561.        {line= symbol.n_desc;
  562.         address= symbol.n_value;
  563.     DBPRINT(("line=%d address=%x\n",line,address));
  564.        }
  565.      else if(type==N_FUN)    /* procedure: name,,0,linenumber,address */
  566.        {funcaddr= symbol.n_un.n_strx;
  567.         address= symbol.n_value;
  568.         funcsymbol= i;
  569.         fseek(fp2,exe.stroffset,0);
  570.         fseek(fp2,funcaddr,1);
  571.         ptr= fgets(ttext,sizeof(ttext),fp2);
  572.         ptr= strtok(ttext,":");
  573.         ll= strlen(ptr);
  574.         if(ll>250){strncpy(funcname,ptr,250); funcname[250]= CNULL;}
  575.         else strcpy(funcname,ptr);
  576.         DBPRINT(("procedure %s address=%x\n",funcname,address));
  577.        }
  578.      else if(type==N_SO)    /* source file name: name,,0,0,address */
  579.        {fileaddr= symbol.n_un.n_strx;
  580.         address= symbol.n_value;
  581.         filesymbol= i;
  582.         fseek(fp2,exe.stroffset,0);
  583.         fseek(fp2,fileaddr,1);
  584.         ptr= fgets(filename,sizeof(filename),fp2);
  585.         DBPRINT(("filename %s address=%x\n",filename,address));
  586.        }
  587.  
  588. /* does this address match one of ours? */
  589.      for(iff=0;iff<nlevel;iff++)
  590.        {if(level[iff].found==0)
  591.          {match= level[iff].programcounter;
  592.           if(address==match)
  593.             {DBPRINT(("exact match of %x found at line %d\n",match,line));
  594.              level[iff].found= 1;
  595.              level[iff].filesymbol= filesymbol;    /* store symbol# of the file */
  596.              level[iff].funcsymbol= funcsymbol; /* symbol# of the function */
  597.              strcpy(level[iff].funcname,funcname);
  598.              strcpy(level[iff].filename,filename);
  599.              level[iff].line= line;
  600.             }
  601.           else if(address>match && lastaddress<match && lastaddress>(match-64))
  602.             {
  603.              DBPRINT(("match of %x before line %d, lastaddress=%x address=%x\n",
  604.              match,line,lastaddress,address));
  605.              level[iff].found= 1;
  606.              level[iff].filesymbol= filesymbol; /* store symbol# of the file */
  607.              level[iff].funcsymbol= funcsymbol; /* symbol# of the function */
  608.              strcpy(level[iff].funcname,funcname);
  609.              strcpy(level[iff].filename,filename);
  610.              level[iff].line= line-1;
  611.             }
  612.          }
  613.        }
  614.      lastaddress= address;
  615.     } /* end of loop over all nsym */
  616.   fclose(fp2);
  617.   fclose(fp);
  618.       
  619. } /* end of trb_getline */
  620.  
  621. /****************************************************************/
  622. /*    trb_params                        */
  623. /*    print one level of parameters                */
  624. /****************************************************************/
  625. static void trb_params(ilevel,fp,fp2)
  626. int ilevel;
  627. FILE *fp, *fp2;
  628. {
  629.   int i,status,type;
  630.   int isym,code,pointer,array;
  631.   int size,middle,sum;
  632.   long addr,off,address,newaddress,stackbase,nseek,contents;
  633.   struct nlist symbol;    /* symbol table entry */
  634.   char *ptr,ttext[1024],symbolname[80],symboltype[80];
  635.   char params[1024],tempstring[1024],outtext[80];
  636.   int ii;
  637.   char cc;
  638.   short ss;
  639.   long ll,l2;
  640.   unsigned char uc;
  641.   unsigned short us;
  642.   unsigned long ul;
  643.   unsigned int ui;
  644.   float ff;
  645.   double dd;
  646.   long vv;
  647. /*------------------------------------*/
  648.   strcpy(params,level[ilevel].funcname);
  649.   strcat(params,"(");
  650.   isym= level[ilevel].funcsymbol+1;
  651.   nseek= exe.symoffset + isym*sizeof(symbol);
  652. /* do a quick loop to get parameter names */
  653.   fseek(fp,nseek,0);
  654.   for(i=isym;i<exe.nsym;i++)
  655.     {status= fread(&symbol,sizeof(symbol),1,fp);
  656.      if(status==0) printf("could not read symbol\n");
  657.      type= symbol.n_type;
  658.      if(type==N_FUN) break;     /* that is all for this function */ 
  659.      else if(type==N_SO) break; /* that is all for this function */
  660.      else if(type==N_PSYM)    /* parameter: name,,0,type,offset */
  661.        {addr= symbol.n_un.n_strx;   /* symbol name in string table */
  662.     fseek(fp2,exe.stroffset,0);
  663.         fseek(fp2,addr,1);
  664.         ptr= fgets(ttext,sizeof(ttext),fp2);
  665.     /* extract the symbol's name */
  666.     strcpy(tempstring,ttext);
  667.     str_whiteout(tempstring,":=;");
  668.     sscanf(tempstring,"%s",symbolname);
  669.     strcat(params,symbolname); strcat(params,",");
  670.        }
  671.     }
  672. /* change the last comma to an )  and print the parameters */
  673.   ll= strlen(params);
  674.   if(params[ll-1]==',') params[ll-1]= ')'; else strcat(params,")");
  675.   fprintf(fpcrash,"%s\n",params);
  676.   
  677.      
  678. /* do a second loop to get values */
  679.   fseek(fp,nseek,0);
  680.   for(i=isym;i<exe.nsym;i++)
  681.     {status= fread(&symbol,sizeof(symbol),1,fp);
  682.      if(status==0) printf("could not read symbol\n");
  683.      type= symbol.n_type;
  684.      if(type==N_FUN) break;     /* that is all for this function */    
  685.      else if(type==N_SO) break; /* that is all for this function */
  686.      else if(type!=N_PSYM)continue;
  687.      addr= symbol.n_un.n_strx;
  688.      off= symbol.n_value;   /* offset from stack frame end */
  689.      fseek(fp2,exe.stroffset,0);
  690.      fseek(fp2,addr,1);
  691.      ptr= fgets(ttext,sizeof(ttext),fp2);
  692.      /* extract the symbol's name */
  693.      strcpy(tempstring,ttext);
  694.      str_whiteout(tempstring,":=;");
  695.      sscanf(tempstring,"%s",symbolname);
  696.      /* extract text we use to get the symbol's type */
  697.      ptr= strchr(ttext,':');
  698.      strcpy(symboltype,ptr);
  699.      stackbase= level[ilevel].frameend;
  700.      address= stackbase+off;    /* where the variable's bytes are */
  701. /* find out what kind of symbol it is */
  702.      trb_translate(ttext,&code,&pointer,&array);
  703. #if PARAMDUMP
  704.      printf("param: >%s< off=%d\n",ttext,off);
  705.      trb_verbalize(symbolname,code,pointer,array);
  706. #endif
  707.  
  708. /* if it is a pointer, print the address & dereference it */
  709.      if(pointer==1)
  710.        {newaddress= *(unsigned long *) address;
  711.         fprintf(fpcrash,"  %s = 0x%x (pointer to %s) \n",
  712.           symbolname, newaddress, description[code]);
  713.         if(newaddress>=0 && newaddress<0x1000) continue;
  714.         else address= newaddress;
  715.        }
  716.      else if(pointer==2)    /* it could be a pointer to a pointer */
  717.        {newaddress= *(unsigned long *) address;
  718.         fprintf(fpcrash,"  %s = 0x%x (pointer to *%s) \n",
  719.           symbolname, newaddress, description[code]);
  720.         if(newaddress>=0 && newaddress<0x1000) continue;
  721.         else address= newaddress;
  722.         newaddress= *(unsigned long *) address;
  723.         if(newaddress>=0 && newaddress<0x1000) continue;
  724.         else address= newaddress;
  725.        }
  726.  
  727. /* treat a ptr to char as an array */
  728.      if(pointer>0 && code==D_CHAR) goto arrays;  /* written by an ex- */
  729.                          /* fortran programmer */
  730. /* an array of any type */
  731.      if(array>1) goto arrays;
  732.  
  733. /* int */
  734.      else if(code==D_INT)
  735.        {ii= *(int *)address;
  736.         sprintf(outtext,"%d 0x%x (long)",ii,ii);}
  737. /* char */
  738.      else if(code==D_CHAR)
  739.        {cc= *(char *)address;
  740.         sprintf(outtext,"\'%c\' 0x%x (char)",cc,cc);}
  741. /* long */
  742.      else if(code==D_LONG)
  743.        {ll= *(long *)address;
  744.         sprintf(outtext,"%d 0x%x (long)",ll,ll);}
  745. /* short */
  746.      else if(code==D_SHORT)
  747.        {ss= *(short *)address;
  748.         sprintf(outtext,"%hd 0x%hx (short)",ss,ss);}
  749. /* unsigned char */
  750.      else if(code==D_UCHAR)
  751.        {uc= *(unsigned char *)address;
  752.         sprintf(outtext,"\'%c\' 0x%x (u char)",uc,uc);}
  753. /* unsigned short */
  754.      else if(code==D_USHORT)
  755.        {us= *(unsigned short *)address;
  756.         sprintf(outtext,"%hd 0x%hx (u short)",us,us);}
  757. /* unsigned long */
  758.      else if(code==D_ULONG)
  759.        {ul= *(unsigned long *)address;
  760.         sprintf(outtext,"%u 0x%x (u long)",ul,ul);}
  761. /* unsigned int */
  762.      else if(code==D_UINT)
  763.        {ui= *(unsigned int *)address;
  764.         sprintf(outtext,"%u 0x%x (u int)",ui,ui);}
  765. /* float */
  766.      else if(code==D_FLOAT)
  767.        {ff= *(float *)address;
  768.         ll= *(long *)address;
  769.         sprintf(outtext,"%f 0x%08x (float)",ff,ll);}
  770. /* double */
  771.      else if(code==D_DOUBLE)
  772.        {dd= *(double *)address;
  773.         ll= *(long *)address;
  774.         l2= *(long *)(address+sizeof(long));
  775.         sprintf(outtext,"%f 0x%08x%08x (double)",dd,ll,l2);}
  776. /* void */
  777.      else if(code==D_VOID)
  778.        {vv= *(long *)address;
  779.         sprintf(outtext,"%d 0x%x (void)",vv,vv);}
  780. /* ??? */
  781.      else
  782.        sprintf(outtext," unknown type ");
  783.  
  784.     
  785.      if(pointer==0)fprintf(fpcrash,"  %s = %s \n",symbolname,outtext);
  786.      else if(pointer==1)fprintf(fpcrash,"  *%s = %s \n",symbolname,outtext);
  787.      else if(pointer==2)fprintf(fpcrash,"  **%s = %s \n",symbolname,outtext);
  788.      continue;
  789.     
  790. /*---------*/
  791. arrays:
  792. /*---------*/
  793.      size= array-1;
  794.      middle= array/2;
  795. /* int or long array */
  796.      if(code==D_INT || code==D_LONG)
  797.        {fprintf(fpcrash,"  %s = an array of type %s \n",
  798.             symbolname,description[code]);
  799.         ii= *(int *)address;
  800.         fprintf(fpcrash,"    %s[0] = %d 0x%x \n", symbolname,ii,ii);
  801.         ii= *(int *) (address+middle*sizeof(int));
  802.         fprintf(fpcrash,"    %s[%d] = %d 0x%x \n", symbolname,middle,ii,ii);
  803.         ii= *(int *) (address+size*sizeof(int));
  804.         fprintf(fpcrash,"    %s[%d] = %d 0x%x \n", symbolname,size,ii,ii);
  805.        }
  806. /* char array */
  807.      else if(code==D_CHAR)
  808.        {sum=pointer;
  809.         if(array>1)sum++;
  810.         else if(sum==1)
  811.           fprintf(fpcrash,"  *%s = \"%s\"\n",symbolname,address);
  812.         else if(sum==2)
  813.           fprintf(fpcrash,"  *%s = \"%s\"\n",symbolname,address);
  814.        }
  815.        
  816. /* float array */
  817.      else if(code==D_FLOAT)
  818.        {fprintf(fpcrash,"  %s = an array of type %s \n",
  819.             symbolname,description[code]);
  820.         ff= *(float *)address;
  821.         fprintf(fpcrash,"    %s[0] = %f 0x%x \n", symbolname,ff,ff);
  822.         ff= *(float *) (address+middle*sizeof(float));
  823.         fprintf(fpcrash,"    %s[%d] = %f 0x%x \n", symbolname,middle,ff,ff);
  824.         ff= *(float *) (address+size*sizeof(float));
  825.         fprintf(fpcrash,"    %s[%d] = %f 0x%x \n", symbolname,size,ff,ff);
  826.        }
  827. /* need to put in other types of arrays */
  828.  
  829.     } /* end of loop over all nsym */
  830.     
  831. } /* end of trb_params */
  832.  
  833. /****************************************************************/
  834. /*    trb_symbols                        */
  835. /*    print local symbols in procedure of interest        */
  836. /****************************************************************/
  837. static void trb_symbols(ilevel,fp,fp2)
  838. int ilevel;
  839. FILE *fp, *fp2;
  840. {
  841.   int i,type,status,isym;
  842.   int code,pointer,array,middle,size;
  843.   long addr,off,address,newaddress,stackbase;
  844.   unsigned long value;
  845.   long nseek;
  846.   struct nlist symbol;    /* symbol table entry */
  847.   char *ptr,ttext[1024],tempstring[1024];
  848.   char symbolname[80],symboltype[80];
  849.   short int jtemp;  unsigned short jtemp2;
  850.   char outtext[80];
  851.   int ii;
  852.   char cc;
  853.   short ss;
  854.   long ll,l2;
  855.   unsigned char uc;
  856.   unsigned short us;
  857.   unsigned long ul;
  858.   unsigned int ui;
  859.   float ff;
  860.   double dd;
  861.   long vv;
  862. /*-----------------------------------*/
  863.   
  864.   isym= level[ilevel].funcsymbol+1;
  865.   nseek= exe.symoffset + isym*sizeof(symbol);
  866.   fseek(fp,nseek,0);
  867.   stackbase= level[ilevel].frameend;
  868.   for(i=isym;i<exe.nsym;i++)
  869.     {status= fread(&symbol,sizeof(symbol),1,fp);
  870.      if(status==0) printf("could not read symbol\n");
  871.      type= symbol.n_type;
  872.      if(type==N_FUN) return;            /* new function */
  873.      else if(type==N_SO) return;        /* new source file */
  874.      else if(type!=N_LSYM) continue;    /* local sym: name,,0,type,offset */
  875.      addr= symbol.n_un.n_strx;          /* pointer to string table */
  876.      off= symbol.n_value;               /* offset from stack frame end */
  877.      fseek(fp2,exe.stroffset,0);
  878.      fseek(fp2,addr,1);
  879.      ptr= fgets(ttext,sizeof(ttext),fp2);
  880.      /* get the symbol's name */
  881.      strcpy(tempstring,ttext);
  882.      str_whiteout(tempstring,":=;");
  883.      sscanf(tempstring,"%s",symbolname);
  884.      /* get text used to find type of symbol */
  885.      ptr= strchr(ttext,':');
  886.      strcpy(symboltype,ptr);
  887.      address= stackbase+off;
  888. /* find out what kind of symbol it is */
  889.      trb_translate(ttext,&code,&pointer,&array);
  890. #if SYMBOLDUMP
  891.      printf("symbol: >%s< off=%d\n",ttext,off);
  892.      trb_verbalize(symbolname,code,pointer,array);
  893. #endif
  894. /* if it is a pointer, print the address & dereference it */
  895.      if(pointer==1)
  896.        {newaddress= *(unsigned long *) address;
  897.         fprintf(fpcrash,"  %s = 0x%x (pointer to %s) \n",
  898.           symbolname, newaddress, description[code]);
  899.         if(newaddress>=0 && newaddress<0x1000) continue;
  900.         else address= newaddress;
  901.        }
  902.      else if(pointer==2)   /* could have pointer to pointer */
  903.        {newaddress= *(unsigned long *) address;
  904.         fprintf(fpcrash,"  %s = 0x%x (pointer to *%s) \n",
  905.           symbolname, newaddress, description[code]);
  906.         if(newaddress>=0 && newaddress<0x1000) continue;
  907.         else address= newaddress;
  908.         newaddress= *(unsigned long *) address;
  909.         if(newaddress>=0 && newaddress<0x1000) continue;
  910.         else address= newaddress;
  911.        }
  912.     
  913. /* treat a ptr to char as an array */
  914.      if(pointer>0 && code==D_CHAR) goto arrays;
  915.  
  916. /* an array of any type */
  917.      if(array>1) goto arrays;
  918.      
  919. /* int */
  920.      else if(code==D_INT)
  921.        {ii= *(int *)address;
  922.         sprintf(outtext,"%d 0x%x (long)",ii,ii);}
  923. /* char */
  924.      else if(code==D_CHAR)
  925.        {cc= *(char *)address;
  926.         sprintf(outtext,"\'%c\' 0x%x (char)",cc,cc);}
  927. /* long */
  928.      else if(code==D_LONG)
  929.        {ll= *(long *)address;
  930.         sprintf(outtext,"%f 0x%x (long)",ll,ll);}
  931. /* short */
  932.      else if(code==D_SHORT)
  933.        {ss= *(short *)address;
  934.         sprintf(outtext,"%hd 0x%hx (short)",ss,ss);}
  935. /* unsigned char */
  936.      else if(code==D_UCHAR)
  937.        {uc= *(unsigned char *)address;
  938.         sprintf(outtext,"\'%c\' 0x%x (u char)",uc,uc);}
  939. /* unsigned short */
  940.      else if(code==D_USHORT)
  941.        {us= *(unsigned short *)address;
  942.         sprintf(outtext,"%hd 0x%hx (u short)",us,us);}
  943. /* unsigned long */
  944.      else if(code==D_ULONG)
  945.        {ul= *(unsigned long *)address;
  946.         sprintf(outtext,"%u 0x%x (u long)",ul,ul);}
  947. /* unsigned int */
  948.      else if(code==D_UINT)
  949.        {ui= *(unsigned int *)address;
  950.         sprintf(outtext,"%u 0x%x (u int)",ui,ui);}
  951. /* float */
  952.      else if(code==D_FLOAT)
  953.        {ff= *(float *)address;
  954.         ll= *(long *)address;
  955.         sprintf(outtext,"%f 0x%08x (float)",ff,ll);}
  956. /* double */
  957.      else if(code==D_DOUBLE)
  958.        {dd= *(double *)address;
  959.         ll= *(long *)address;
  960.         l2= *(long *)(address+sizeof(long));
  961.         sprintf(outtext,"%f 0x%08x%08x (double)",dd,ll,l2);}
  962. /* void */
  963.      else if(code==D_VOID)
  964.        {vv= *(long *)address;
  965.         sprintf(outtext,"%d 0x%x (void)",vv,vv);}
  966. /* ??? */
  967.      else
  968.        sprintf(outtext," unknown type ");
  969.     
  970.  
  971.      if(pointer==0)fprintf(fpcrash,"  %s = %s \n",symbolname,outtext);
  972.      else if(pointer==1)fprintf(fpcrash,"  *%s = %s \n",symbolname,outtext);
  973.      continue;
  974. /*---------*/
  975. arrays:
  976. /*---------*/
  977.      size= array-1;
  978.      middle= array/2;
  979. /* int or long array */
  980.      if(code==D_INT || code==D_LONG)
  981.        {fprintf(fpcrash,"  %s = an array of type %s \n",
  982.             symbolname,description[code]);
  983.         ii= *(int *)address;
  984.         fprintf(fpcrash,"    %s[0] = %d 0x%x \n", symbolname,ii,ii);
  985.         ii= *(int *) (address+middle*sizeof(int));
  986.         fprintf(fpcrash,"    %s[%d] = %d 0x%x \n", symbolname,middle,ii,ii);
  987.         ii= *(int *) (address+size*sizeof(int));
  988.         fprintf(fpcrash,"    %s[%d] = %d 0x%x \n", symbolname,size,ii,ii);
  989.        }
  990. /* char array */
  991.      else if(code==D_CHAR)
  992.        fprintf(fpcrash,"  %s = \"%s\" \n",symbolname,address);
  993. /* float array */
  994.      else if(code==D_FLOAT)
  995.        {fprintf(fpcrash,"  %s = an array of type %s \n",
  996.             symbolname,description[code]);
  997.         ff= *(float *)address;
  998.         ll= *(long *)address;
  999.         fprintf(fpcrash,"    %s[0] = %f 0x%x \n", symbolname,ff,ll);
  1000.         ff= *(float *) (address+middle*sizeof(float));
  1001.         ll= *(long *) (address+middle*sizeof(float));
  1002.         fprintf(fpcrash,"    %s[%d] = %f 0x%x \n", symbolname,middle,ff,ll);
  1003.         ff= *(float *) (address+size*sizeof(float));
  1004.         ll= *(long *) (address+size*sizeof(float));
  1005.         fprintf(fpcrash,"    %s[%d] = %f 0x%x \n", symbolname,size,ff,ll);
  1006.        }
  1007. /* dump other kinds of arrays */
  1008.  
  1009.     } /* end of loop over all nsym */
  1010.  
  1011. } /* end of trb_symbols */
  1012.  
  1013. /****************************************************************/
  1014. /*    trb_traceback                        */
  1015. /*    print a traceback                     */
  1016. /****************************************************************/
  1017. static void trb_traceback(nlevel)
  1018. int nlevel;
  1019. {
  1020.   int i;
  1021.   FILE *fp,*fp2;
  1022. /*---------------------------*/
  1023.   if(nlevel<1)return;
  1024. /* use first file pointer to read the symbol table */
  1025.   fp= fopen(exe.name,"r");
  1026.   if(fp==NULL) {printf("can't open %s\n",exe.name);exit(1);}
  1027. /* use second file pointer to read the string table */
  1028.   fp2= fopen(exe.name,"r");
  1029.  
  1030. /* print a traceback to the screen */
  1031.   fprintf(fpcrash,"---------- traceback ----------\n");
  1032.   for(i=0;i<nlevel;i++)
  1033.     if(level[i].found!=0)fprintf(fpcrash,"file %s line %d function %s() \n",
  1034.        level[i].filename, level[i].line, level[i].funcname);
  1035.      else
  1036.        fprintf(fpcrash,"address %x \n", level[i].programcounter);
  1037.  
  1038.   for(i=0;i<nlevel;i++)
  1039.     {
  1040.      fprintf(fpcrash,"------------------------------------\n");
  1041.      if(level[i].found!=0)
  1042.        {
  1043.         trb_dictionary(i,fp,fp2);
  1044.         trb_params(i,fp,fp2);
  1045.         fprintf(fpcrash,"  -- local symbols for %s --\n",level[i].funcname);
  1046.         trb_symbols(i,fp,fp2);
  1047.        }
  1048.     }
  1049.   
  1050.   fclose(fp2);
  1051.   fclose(fp);
  1052.        
  1053. } /* end of trb_traceback */
  1054.  
  1055. /****************************************************************/
  1056. /*    trb_userinfo                        */
  1057. /*    put program name, user, etc into a file            */
  1058. /****************************************************************/
  1059. void trb_userinfo(fp)
  1060. FILE *fp;
  1061. {
  1062.   int ll;
  1063.   char *user,host[64],nouser[8];
  1064.   time_t timeofday;
  1065.   char fulltime[26];
  1066. /* get the user's name */
  1067.   user= (char *) getlogin();
  1068.   if(user==NULL)user= (char *)getpwuid(getuid());
  1069.   if(user==NULL){strcpy(nouser,"????"); user=nouser; }
  1070.   
  1071. /* get the time */
  1072.   timeofday=time((time_t *)0);
  1073.   strcpy(fulltime,ctime(&timeofday));
  1074.   fulltime[24]=CNULL;
  1075. /* get the host */
  1076.   gethostname(host,64);
  1077. /* write to a file */
  1078.   fprintf(fp,"user=%s host=%s date=%s \n", user,host,fulltime);
  1079.   fprintf(fp,"program=%s \n", exe.name);
  1080. } /* end of trb_userinfo */
  1081.  
  1082. /****************************************************************/
  1083. /*    trb_handle                        */
  1084. /*    handle all signals                    */
  1085. /****************************************************************/
  1086. void trb_handle(sig,code,scp,addr)
  1087. int sig, code;
  1088. struct sigcontext *scp;
  1089. char *addr;
  1090. {
  1091.   int i,j,exitflag;
  1092.   int nlevel;
  1093.   unsigned long programcounter,stackpointer,frameend;
  1094.   unsigned long instruction;
  1095.   char *ptr;
  1096.   char *startdump;
  1097. /*--------------------*/
  1098. /* write to a file called CRASH */
  1099.   if(fpcrash==0) fpcrash= fopen("CRASH","a");    /* open for append */
  1100.   if(fpcrash==NULL) fpcrash= stdout;     /* if failure, use standard output */
  1101.   fprintf(fpcrash,"vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n");
  1102.   trb_userinfo(fpcrash);
  1103. /* print meaningful message for signal */
  1104.   fprintf(fpcrash,"%s signal=%d(%d) \n",sigtext[sig],sig,code);
  1105.   ptr= trb_codetext(sig,code);
  1106.   if(ptr!=NULL) fprintf(fpcrash,"%s\n",ptr);
  1107.   if( (long)addr > 0x1000)     /* had a value 0f 0x2 once */
  1108.     {instruction= *(long *) addr; 
  1109.      fprintf(fpcrash,"instruction is %X \n",instruction);
  1110.     }
  1111. /* get stack pointer & program counter */
  1112.   programcounter= scp->sc_pc;
  1113.   stackpointer= scp->sc_sp;
  1114.   frameend= *( (long *)stackpointer +JUMPSP);
  1115.   DBPRINT((" pc=0x%x sp=0x%x \n", programcounter,stackpointer));
  1116.  
  1117. #if STACKDUMP
  1118.   startdump= (char *)scp->sc_sp;
  1119.   startdump= startdump-16;
  1120.   trb_stackdump(startdump,DUMPSIZE,&fpstackdump);
  1121. #endif
  1122.  
  1123. /* walk the stack, storing stack pointers & program counters */
  1124.   nlevel= 0;
  1125.   while(stackpointer!=0)
  1126.     {level[nlevel].programcounter= programcounter;
  1127.      level[nlevel].frameend= frameend;
  1128.      level[nlevel].stackpointer= stackpointer;
  1129.      if(nlevel<MAXLEVEL)nlevel++;
  1130.      DBPRINT(("sp=%08x pc=%08x\n",stackpointer,programcounter));
  1131. #if FRAMEDUMP
  1132.      trb_framedump(stackpointer,programcounter,frameend,&fpframedump);
  1133. #endif
  1134.      programcounter= *( (long *)stackpointer +JUMPPC);
  1135.      stackpointer= *( (long *)stackpointer +JUMPSP);
  1136.      if(stackpointer!=0) frameend= *( (long *)stackpointer +JUMPSP);
  1137.      if(frameend==0) stackpointer= 0; /* we are at the end */
  1138.     }
  1139.  
  1140.   trb_exeinfo();        /* get info from file header */
  1141.   trb_getline(nlevel);        /* convert addresses to line numbers */
  1142.   trb_traceback(nlevel);    /* print a full traceback */
  1143. #if SYMBOLDUMP
  1144.   trb_symboldump();
  1145. #endif
  1146.  
  1147.   exitflag= 0;
  1148.   switch(sig)
  1149.     {case SIGTRAP:        exitflag= 1;    break;
  1150.      case SIGSEGV:        exitflag= 1;    break; 
  1151.      case SIGABRT:        exitflag= 1;    break;
  1152.      case SIGBUS:        exitflag= 1;    break;
  1153.      case SIGILL:        exitflag= 1;    break;
  1154.      case SIGFPE:        
  1155.        switch(code)
  1156.           {case FPE_INTOVF_TRAP:    exitflag= 1;    break;
  1157.            case FPE_STARTSIG_TRAP:    exitflag= 1;    break;
  1158.            case FPE_INTDIV_TRAP:    exitflag= 1;    break;
  1159.            case FPE_FLTINEX_TRAP:    exitflag= 1;    break;
  1160.            case FPE_FLTDIV_TRAP:    exitflag= 1;    break;
  1161.            case FPE_FLTUND_TRAP:    exitflag= 1;    break;
  1162.            case FPE_FLTOPERR_TRAP:    exitflag= 1;    break;
  1163.            case FPE_FLTOVF_TRAP:    exitflag= 1;    break;
  1164.            default:            break;
  1165.           }
  1166.        break; /* end of SIGFPE */
  1167.      default:            
  1168.        printf("signal %d sent to trb_handle \n",sig);
  1169.        break;
  1170.     } /* end of switch on sig */
  1171.   fprintf(fpcrash,"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
  1172. #if FRAMEDUMP
  1173.   fclose(fpframedump);
  1174. #endif
  1175.   if(exitflag) 
  1176.     {if(fpcrash!=stdout) {fclose(fpcrash); system("ls -l CRASH");}
  1177.      exit(sig);
  1178.     }
  1179.   return;
  1180. } /* end of trb_handle */
  1181.  
  1182. /****************************************************************/
  1183. /*    trb_sigtextinit                        */
  1184. /*    initialize signal text messages                */
  1185. /****************************************************************/
  1186. static void trb_sigtextinit()
  1187. {
  1188.   strcpy(sigtext[1],  "SIGHUP:  hangup signal received");
  1189.   strcpy(sigtext[2],  "SIGINT:  interrupt signal received");
  1190.   strcpy(sigtext[3],  "SIGQUIT: quit signal received");
  1191.   strcpy(sigtext[4],  "SIGILL:  illegal instruction (not reset when caught)");
  1192.   strcpy(sigtext[5],  "SIGTRAP: trace trap (not reset when caught)");
  1193.   strcpy(sigtext[6],  "SIGABRT: abort or IOT instruction");
  1194.   strcpy(sigtext[7],  "SIGEMT:  EMT instruction");
  1195.   strcpy(sigtext[8],  "SIGFPE:  floating point exception");
  1196.   strcpy(sigtext[9],  "SIGKILL: kill signal received");
  1197.   strcpy(sigtext[10],  "SIGBUS:  bus error");
  1198.   strcpy(sigtext[11], "SIGSEGV: segmentation violation");
  1199.   strcpy(sigtext[12], "SIGSYS:  bad argument to system call");
  1200.   strcpy(sigtext[13], "SIGPIPE: write on a pipe with no one to read it");
  1201.   strcpy(sigtext[14], "SIGALRM: alarm clock signal received");
  1202.   strcpy(sigtext[15], "SIGTERM: received software termination signal");
  1203.   strcpy(sigtext[16], "SIGURG:  urgent condition on IO channel");
  1204.   strcpy(sigtext[17], "SIGSTOP: sendable stop signal not from tty");
  1205.   strcpy(sigtext[18], "SIGTSTP: received stop signal from tty");
  1206.   strcpy(sigtext[19], "SIGCONT: continue a stopped process");
  1207.   strcpy(sigtext[20], "SIGCHLD: child process has stopped or exited");
  1208.   strcpy(sigtext[21], "SIGTTIN: to readers pgrp upon background tty read");
  1209.   strcpy(sigtext[22], "SIGTTOU: like TTIN for output if (tp->t_local<OSTOP)");
  1210.   strcpy(sigtext[23], "SIGIO:   input/output possible signal");
  1211.   strcpy(sigtext[24], "SIGXCPU: exceeded CPU time limit");
  1212.   strcpy(sigtext[25], "SIGXFSZ: exceeded file size limit");
  1213.   strcpy(sigtext[26], "SIGVTALRM: received virtual time alarm");
  1214.   strcpy(sigtext[27], "SIGPROF: received profiling time alarm");
  1215.   strcpy(sigtext[28], "SIGWINCH: window changed");
  1216.   strcpy(sigtext[29], "SIGLOST: resource lost (eg, record-lock lost)");
  1217.   strcpy(sigtext[30], "SIGUSR1: received user defined signal 1");
  1218.   strcpy(sigtext[31], "SIGUSR2: received user defined signal 2");
  1219. } /* end if trb_sigtextinit */
  1220.  
  1221. /****************************************************************/
  1222. /*    trb_codetext                        */
  1223. /*    return text explanation of signal            */
  1224. /****************************************************************/
  1225. static char *trb_codetext(sig,code)
  1226. int sig,code;
  1227. {
  1228.   if(sig==SIGILL)
  1229.     {if(code==ILL_STACK) return("bad stack");
  1230.      else if(code==ILL_ILLINSTR_FAULT) return("illegal instruction fault");
  1231.      else if(code==ILL_PRIVINSTR_FAULT) return("privileged instruction fault");
  1232.      else if(code>=0x80 & code<=0xff) return("software trap");
  1233.      else return(NULL);
  1234.     }
  1235.   else if(sig==SIGFPE)
  1236.     {if(code==FPE_INTOVF_TRAP) return("integer overflow");
  1237.      else if(code==FPE_STARTSIG_TRAP) return("process using fp");
  1238.      else if(code==FPE_INTDIV_TRAP) return("integer divide by zero");
  1239.      else if(code==FPE_FLTINEX_TRAP) return("floating inexact result");
  1240.      else if(code==FPE_FLTDIV_TRAP) return("floating divide by zero");
  1241.      else if(code==FPE_FLTUND_TRAP) return("floating underflow");
  1242.      else if(code==FPE_FLTOPERR_TRAP) return("floating operand error");
  1243.      else if(code==FPE_FLTOVF_TRAP) return("floating overflow");
  1244.      else return(NULL);
  1245.     }
  1246.   else if(sig==SIGBUS)
  1247.     {if(code==BUS_HWERR) return("misc hardware error (e.g. timeout)");
  1248.      else if(code==BUS_ALIGN) return("hardware alignment error");
  1249.      else if(code==BUS_OBJERR) return("object returned errno value");
  1250.      else return(NULL);
  1251.     }
  1252.   else if(sig==SIGSEGV)
  1253.     {if(code==SEGV_NOMAP) return("no mapping at the fault address");
  1254.      else if(code==SEGV_PROT) return("access exceeded protections");
  1255.      else if(code==SEGV_OBJERR) return("object returned errno value");
  1256.      else return(NULL);
  1257.     }
  1258.   else
  1259.     return(NULL);
  1260. } /* end of trb_codetext */
  1261.  
  1262. /****************************************************************/
  1263. /*    trb_signal                        */
  1264. /*    initiate trapping of all signals            */
  1265. /****************************************************************/
  1266. static void trb_signal()
  1267. {
  1268.   int status;
  1269.   sigfpe_handler_type funcname;
  1270. /*---------------------------------------*/
  1271.   trb_sigtextinit();
  1272. /* trap the important signals */
  1273. /*  signal(SIGILL,trb_handle);  
  1274.   signal(SIGTRAP,trb_handle); */
  1275.   signal(SIGFPE,trb_handle);      /* floating point errors */
  1276.   signal(SIGBUS,trb_handle);      /* bus errors */
  1277.   signal(SIGSEGV,trb_handle);     /* segmentation faults */
  1278.   signal(SIGABRT,trb_handle);      /* to get integer divide */
  1279. /* don't trap the rest */
  1280. #if 0
  1281.   signal(SIGHUP,trb_handle);  
  1282.   signal(SIGINT,trb_handle);  
  1283.   signal(SIGQUIT,trb_handle); 
  1284.   signal(SIGEMT,trb_handle);  
  1285.   signal(SIGKILL,trb_handle);
  1286.   signal(SIGSYS,trb_handle);  
  1287.   signal(SIGPIPE,trb_handle); 
  1288.   signal(SIGALRM,trb_handle); 
  1289.   signal(SIGTERM,trb_handle); 
  1290.   signal(SIGURG,trb_handle);  
  1291.   signal(SIGSTOP,trb_handle); 
  1292.   signal(SIGTSTP,trb_handle); 
  1293.   signal(SIGCONT,trb_handle); 
  1294.   signal(SIGCHLD,trb_handle); 
  1295.   signal(SIGTTIN,trb_handle); 
  1296.   signal(SIGTTOU,trb_handle); 
  1297.   signal(SIGIO,trb_handle);   
  1298.   signal(SIGXCPU,trb_handle); 
  1299.   signal(SIGXFSZ,trb_handle); 
  1300.   signal(SIGVTALRM,trb_handle); 
  1301.   signal(SIGPROF,trb_handle); 
  1302.   signal(SIGWINCH,trb_handle); 
  1303.   signal(SIGLOST,trb_handle); 
  1304.   signal(SIGUSR1,trb_handle);
  1305.   signal(SIGUSR2,trb_handle);
  1306. #endif
  1307. /* invoke special ieee handler to catch integer divide by zero */
  1308.   funcname= (sigfpe_handler_type)trb_handle;
  1309.   status= ieee_handler("set","all",funcname);
  1310.   if(status!=0)printf("can't set ieee all\n");
  1311. /* ignore inexact representation of float point numbers */
  1312.   status= ieee_handler("clear","inexact",funcname);
  1313.   if(status!=0)printf("can't clear ieee inexact\n");
  1314. } /* end of trb_signal */
  1315.  
  1316. /****************************************************************/
  1317. /*    trb_signalinit                        */
  1318. /*    initiate trapping of all signals            */
  1319. /****************************************************************/
  1320. void trb_signalinit(argc,argv)
  1321. int argc;
  1322. char *argv[];
  1323. {
  1324.   FILE *fp;
  1325. /*---------------------------------------*/
  1326. /* find the executable file */
  1327.   trb_exefind(argc,argv);
  1328. /* remove files CRASH, STACKDUMP, & FRAMEDUMP */
  1329.   fp= fopen("CRASH","w");
  1330.   if(fp!=NULL) fclose(fp);    
  1331.   fp= fopen("STACKDUMP","w");
  1332.   if(fp!=NULL) fclose(fp);    
  1333.   fp= fopen("FRAMEDUMP","w");
  1334.   if(fp!=NULL) fclose(fp);
  1335.   fpcrash= 0;
  1336.   fpstackdump= 0;  
  1337.   fpframedump= 0;  
  1338. /* set up our signal handler */
  1339.   trb_signal();
  1340. } /* end of ita_signalinit */
  1341.  
  1342.  
  1343. /*****************************************************************/
  1344. /*    strstr                                                   */
  1345. /*    returns a pointer to first occurence of a substring      */
  1346. /*****************************************************************/
  1347. static char *strstr(string,phrase)
  1348. char *string,*phrase;
  1349. {
  1350.   char *ptr1, *ptr2;
  1351. /*------------------------------------------------------*/
  1352.   if(strlen(string)==0) return(NULL);
  1353.   if(strlen(phrase)==0) return(NULL);
  1354.   
  1355.   for (; (string= strchr(string, *phrase)) !=NULL; ++string)
  1356.     {for (ptr1= string, ptr2= phrase; ;)
  1357.        if(*++ptr2 == CNULL) return (string);
  1358.        else if (*++ptr1 != *ptr2)break;
  1359.     }
  1360.   return (NULL);
  1361. }
  1362.  
  1363. /**************************************************************/
  1364. /*    str_getdelimited                                      */
  1365. /*    returns substring bounded by 2 characters          */
  1366. /**************************************************************/
  1367. static void str_getdelimited(intext,bounds,outtext)
  1368. char *intext,*bounds,*outtext;
  1369. {
  1370.   int ll;
  1371.   char start, end;
  1372.   char *ptr, *ptr2;
  1373. /*------------------------------------------------------*/
  1374.   outtext[0]=CNULL;
  1375.   start= bounds[0];
  1376.   end= bounds[1];  
  1377.   ptr=strchr(intext,start);
  1378.   if(ptr==NULL)return;
  1379.   ptr++;
  1380.   ptr2=strchr(ptr,end);
  1381.   if(ptr2==NULL)return;
  1382.   ll=ptr2-ptr;
  1383.   strncpy(outtext,ptr,ll);
  1384.   outtext[ll]=CNULL;
  1385. }
  1386.  
  1387. /********************************************************/
  1388. /*    str_whiteout                    */
  1389. /*    routine to change certain characters to blanks     */
  1390. /********************************************************/
  1391. static void str_whiteout(string,chars)
  1392. char *string,*chars;
  1393. {
  1394. /*... locals */
  1395.   int i,j,ls,lc;
  1396.   char cc;
  1397. /*-----------------------------*/
  1398.   ls=strlen(string);
  1399.   if(ls<1)return;
  1400.   lc=strlen(chars);
  1401.   if(lc<1)return;
  1402.   for(i=0;i<ls;i++)
  1403.     {cc=string[i];
  1404.      for(j=0;j<lc;j++)if(cc==chars[j])cc=' ';
  1405.      string[i]=cc;
  1406.     }
  1407. } /* end of str_whiteout */
  1408.   
  1409.